vector<int> edge[MAXN]; int depth[MAXN]; // 节点深度 int up[MAXN][LOG]; // up[u][i]: u向上走2^i步到达的祖先 // 1. DFS预处理深度和倍增表 (递归版,注意栈溢出风险,可用BFS) voiddfs(int u, int fa){ depth[u] = depth[fa] + 1; up[u][0] = fa; // 走2^0步即父节点 for (int i = 1; i < LOG; i++) { // 核心转移:2^i = 2^(i-1) + 2^(i-1) up[u][i] = up[ up[u][i-1] ][i-1]; } for (int v : edge[u]) { if (v == fa) continue; dfs(v, u); } }
// 2. 将节点u向上跳diff步 (二进制拆分) intjump(int u, int diff){ for (int i = 0; diff; i++, diff >>= 1) { if (diff & 1) u = up[u][i]; } return u; }
// 3. 查询LCA intlca(int u, int v){ if (depth[u] < depth[v]) swap(u, v); // Step 1: 把u提到和v同一深度 int diff = depth[u] - depth[v]; for (int i = 0; i < LOG; i++) { if (diff & (1 << i)) u = up[u][i]; } if (u == v) return u; // Step 2: 从高位往低位尝试,如果祖先不同就跳上去 for (int i = LOG - 1; i >= 0; i--) { if (up[u][i] != up[v][i]) { u = up[u][i]; v = up[v][i]; } } return up[u][0]; // 返回父节点 }
// 4. 求树上两点距离 (需要预处理根到节点距离dist) intgetDist(int u, int v){ int anc = lca(u, v); return depth[u] + depth[v] - 2 * depth[anc]; } signedmain(){ int n; cin>>n; string s; cin>>s; s=' '+s; for (int i=1;i<n;i++){ int u,v;cin>>u>>v; edge[u].push_back(v); edge[v].push_back(u); } dfs(1,0); vector<int> red; for (int i=1;i<=n;i++){ if (s[i]=='1') { red.push_back(i); } } int t=red[0]; int mxd=0; int A=red[0],B=0; for (int v:red){ int dis=getDist(t,v); if (dis>mxd){ mxd=dis; A=v; } } mxd=0; for (int v:red){ int dis=getDist(A,v); if (dis>mxd){ mxd=dis; B=v; } } for (int i=1;i<=n;i++){ if (s[i]=='1'){ cout<<mxd<<endl; continue; } cout<<max(mxd,max(getDist(i,A),getDist(i,B)))<<endl;; } return0; }